package goredis

import (
	"context"
	"fmt"
	"net"

	"github.com/redis/go-redis/v9"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
)

// dbConn 数据库连接信息
var dbConn = make(map[string]*redis.Client)

// Conn 数据库连接信息
type Conn struct {
	ConfName string
	Host     string
	Port     string
	Pwd      string
	Database string
}

type LogHook struct {
	Logger *logrus.Logger
}

func (*LogHook) DialHook(next redis.DialHook) redis.DialHook {
	return func(ctx context.Context, network, addr string) (net.Conn, error) {
		return next(ctx, network, addr)
	}
}

func (xx *LogHook) ProcessHook(next redis.ProcessHook) redis.ProcessHook {
	return func(ctx context.Context, cmd redis.Cmder) error {
		err := next(ctx, cmd)
		if err != nil {
			xx.Logger.WithContext(ctx).WithField("type", "redis").Infof("%s,%+v", cmd.String(), err)
		} else {
			xx.Logger.WithContext(ctx).WithField("type", "redis").Infof("%s", cmd.String())
		}
		return err
	}
}

func (*LogHook) ProcessPipelineHook(next redis.ProcessPipelineHook) redis.ProcessPipelineHook {
	return func(ctx context.Context, cmds []redis.Cmder) error {
		return next(ctx, cmds)
	}
}

// NewClient 创建数据库链接
func NewClient(conf *Conn, logger *logrus.Logger) (*redis.Client, error) {
	if dbConn[conf.ConfName] != nil {
		return dbConn[conf.ConfName], nil
	}
	addr := fmt.Sprintf("%s:%s", conf.Host, conf.Port)
	rdb := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: conf.Pwd,                  // password set
		DB:       cast.ToInt(conf.Database), // use default DB
		PoolSize: 100,
	})
	rdb.AddHook(&LogHook{Logger: logger})
	dbConn[conf.ConfName] = rdb
	return dbConn[conf.ConfName], nil
}

// Close 关闭redis
func Close() {
	for k, db := range dbConn {
		fmt.Println("关闭redis连接", k)
		err := db.Close()
		if err != nil {
			fmt.Println("关闭redis连接失败", k, err.Error())
		} else {
			fmt.Println("关闭redis连接成功", k)
		}
	}
}
